/******************************************************************************
 * Copyright (C), 2014, BeeIoT Tech. Co., Ltd. 
 * FileName:        sim900a_core.c
 * Author:          lvxin 
 * Version :        1.0
 * Date:            2015-01-08 14:48:57
 * Description:
 * Function List:   1. -------
 * History:
 * <author>     <time>                <version >  <desc> 
 * lvxin        2015-01-08 14:48:57   1.0         build this moudle 
 *****************************************************************************/

/******************************************************************************
 *  *INCLUDES
 *  */
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "sim900a_core.h"

/******************************************************************************
 *  *MICROS
 *  */
#define     DIM(x)  (sizeof(x)/sizeof(x[0]))

/******************************************************************************
 *  *TYPEDEFS
 *  */
//命令行最终响应状态
typedef struct _cmd_ret
{
    char *key;
    int value;
}cmd_ret_t;

//SIM900A状态结构
typedef struct _sim900a_core_statue
{
    char busy;      //信息正在处理 1正在处理  0空闲
}SIM900A_core_stat_t;


/******************************************************************************
 *  *CONSTANTS
 *  */
const cmd_ret_t l_cmd_ret_value[]={
    {"OK",      AT_RETURN_OK},
    {"ERROR",   AT_RETURN_ERROR},
    {">",       AT_RETURN_CON},
    {"SEND OK", AT_RETURN_SENDOK},
    {"SHUT OK", AT_RETURN_SHUTOK},
    {"CLOSE OK", AT_RETURN_CLOSEOK},
};

/******************************************************************************
 *  *EXTERNAL FUNCTIONS
 *  */
extern void mdelay (uint32_t time);

/******************************************************************************
 *  *LOCAL VARIABLES
 *  */

static SIM900A_core_stat_t l_sim_stat = {0};        //SIM900A状态结构体,
                                                    //每次refresh均处理本结构体
static SIM900A_cmdline_t l_sim_cmdline;             //处理串口收到的字符流
static serial_buffer_t l_serial_buffer = {0, {0}};  //接收串口数据
static SIM900A_cmdline_t l_sim_cmdline;             //处理串口收到的字符流

/******************************************************************************
 *  *FUNCTION DECLARES
 *  */
static int   _SIM900A_parse_input(SIM900A_cmdline_t *input);//分析串口命令行数据 
static void  _cmd_callback(int retstat);
static int   _SIM900A_parse_cmd_ret_stat(const char *__restrict data); //分析命令行返回状态

/******************************************************************************
 *  *LOCAL FUNCTIONS
 *  */
/*******************************************************************************
 * Function:      SIM900A_parse_input()
 * Description:   分析串口命令行数据
 * Calls:          
 * Called By:     SIM900A_read()  
 * Input:         获取串口的命令行
 * Return:         
 * Others:        None
 ******************************************************************************/
static int _SIM900A_parse_input(SIM900A_cmdline_t *input)
{
    int cmd_ret_value = -1;
    if(input->buffer[0] == '\r' && input->buffer[1] == '\n')
    {
        return 0;
    }
    else
    {
        if (input->cmdline_running == 1) //表示命令行指令执行中,主动模式
        {
            /*分析命令行状态*/
            cmd_ret_value = _SIM900A_parse_cmd_ret_stat(input->buffer);

            /*当遇到有效返回状态字符串时表示输入的AT指令执行结束*/
            if(cmd_ret_value != AT_RETURN_UNKNOWN)
            {
                /*strncpy (input->retStr, input->buffer, RET_STAT_MAX_LEN); //命令行结束状态*/
                input->retstat = cmd_ret_value; //保存返回状态
                input->cmd_callback(input->retstat);
                input->cmdline_running = 0; //命令执行完成
                /*memset (input->last_cmd, 0, LAST_CMD_MAX_LEN); //清除指令缓冲区*/
            }
            else
            {
                /*strncpy (input->dest, input->buffer, DATA_BUFFER_MAX_LEN);*/
                strncat (input->dest, input->buffer, DATA_BUFFER_MAX_LEN - strlen (input->dest));
            }
        }
        else  //被动模式
        {
            input->idle_callback (input->buffer);
        }
    }
    return 0;
}

static void _cmd_callback(int retstat)
{
#if (PLATFORM == LINUX)
    DBG_PRINTF ("[VALUE] %s\n", SIM900A_core_get_cmdline_dest());
    DBG_PRINTF ("[STAT] %d\n=================================\n", retstat);
#endif
}

//分析命令行返回状态
static int _SIM900A_parse_cmd_ret_stat(const char *__restrict data)
{
    int i;
    int n = DIM(l_cmd_ret_value);
    for (i = 0; i < n; i ++)
    {
        if (strncmp(l_cmd_ret_value[i].key, data, strlen(l_cmd_ret_value[i].key)) == 0)
        /*if (strcmp(l_cmd_ret_value[i].key, data) == 0)*/
        {
            return l_cmd_ret_value[i].value;
        }
    }
    return AT_RETURN_UNKNOWN;
}


/******************************************************************************
 *  *PUBLIC FUNCTIONS
 *  */

#if (PLATFORM == LINUX)
#include <stdarg.h>
/*******************************************************************************
 * Function:      _write()
 * Description:   底层接口，通过串口发送数据
 * Calls:          
 * Called By:     SIM900A_parse_input()    
 *                SIM900A_run()
 * Input:         data  --要发送的数据
 *                len   --数据长度
 * Return:        None
 * Others:        None
 ******************************************************************************/
static int __write (const char *data, int len)
{
    extern cssl_t *serial;
    cssl_putdata (serial, (uint8_t *)data, len);
    return 0;
}

void SIM900A_core_uprintf(char *fmt, ...)
{
    va_list va;
    char buf[1024];
    va_start(va, fmt);
    memset(buf, 0, 1024);
    (void) vsprintf(buf, fmt, va);
    /*DBG_PRINTF ("%s\n", buf);*/
    __write (buf, strlen (buf));
    va_end(va);
}
void SIM900A_core_uvprintf(char *fmt, va_list va)
{
    char buf[1024];
    memset(buf, 0, 1024);
    (void) vsprintf(buf, fmt, va);
    /*DBG_PRINTF ("%s\n", buf);*/
    __write (buf, strlen (buf));
}
#endif

/*
 ******************************************************************************
 * Function:      SIM900A_run()
 * Description:   发送执行AT指令，并返回执行结果
 * Calls:          
 * Called By:      
 * Input:         cmdline   --命令行
 *                timeout   --命令执行超时
 *                ret_content --用来存储命令执行过程中发来的内容
 *                proc      --执行后处理
 * Return:        0   --执行成功
 *                1   --执行失败
 *                2   --命令行失效
 *                -1  --命令执行超时
 * Others:         
 ******************************************************************************
 */
int SIM900A_perform_formatted(int timeout, char **ret_content, int (*proc)(char *, int), 
     const char *__restrict __fmt, ...)
{
    va_list va;
    int count = 0;
    int ret = 1;

    mdelay(10);
    va_start(va, __fmt);
    /*vprintf (__fmt, va);*/
    DBG_PRINTF ("[ATCOM]:");
    DBG_VPRINTF (__fmt, va);

    while (l_sim_stat.busy == 1){
        if (++ count > timeout)
        {
            /*DBG_PRINTF ("error\n");*/
            l_sim_stat.busy = 0;
            return AT_RETURN_BUSY;  //命令执行正忙
        }
        mdelay (1);
#if (PLATFORM == LPC1114)
        FEED_DOG();
#endif
    };                       //系统正忙,等待上一条指令完成

    l_sim_stat.busy = 1;                                  //命令执行中

    l_sim_cmdline.cmdline_running = 1 ;                      //设置标志命令执行中

    l_sim_cmdline.retstat = AT_RETURN_UNKNOWN; //还原ret状态
    memset (l_sim_cmdline.dest,   0, DATA_BUFFER_MAX_LEN );  //清除命令执行期间收到的数据缓冲区
    /*memset (l_sim_cmdline.buffer,   0, SERIAL_INPUT_BUFFER_MAX_LEN); //清除缓冲区 */

    SIM900A_core_uvprintf((char *)__fmt, va);
    va_end(va);

    while (l_sim_cmdline.cmdline_running != 0)
    {
        if (++ count > timeout)
        {
            l_sim_stat.busy = 0;
            l_sim_cmdline.cmdline_running = 0 ;  //设置标志,命令执行完成
            return AT_RETURN_TIME_OUT;  //命令执行超时
        }
        mdelay (1);
#if (PLATFORM == LPC1114)
        FEED_DOG();
#endif
    }
    if (ret_content != NULL)
    {
        *ret_content = l_sim_cmdline.dest;
    }

    ret = l_sim_cmdline.retstat;

    if (proc != NULL)
    {
        ret = proc (l_sim_cmdline.dest, strlen (l_sim_cmdline.dest)); //处理数据
    }
    l_sim_stat.busy = 0;
    return ret;
}

void SIM900A_core_disable_uart_recv(void)
{
    l_serial_buffer.recv_en = 0;
}

void SIM900A_core_enable_uart_recv(void)
{
    l_serial_buffer.recv_en = 1;
}


//空闲情况下收到的信息处理
void SIM900A_core_set_passive_cb(void (*idle_callback)(char *buffer))
{
    l_sim_cmdline.idle_callback = idle_callback; 
}


char * SIM900A_core_get_cmdline_dest(void)
{
    return l_sim_cmdline.dest;
}

void SIM900A_core_clean_uart_rxbuf(void)
{
    memset (l_sim_cmdline.buffer,   0, SERIAL_INPUT_BUFFER_MAX_LEN); //清除缓冲区
}


//sim900a内核初始化
void SIM900A_core_init(void)
{
    SIM900A_core_enable_uart_recv();//开启串口接收使能
    l_sim_cmdline.cmd_callback  = _cmd_callback;
}

/*******************************************************************************
 * Function:      SIM900A_core_getch()
 * Description:   从串口读取一个字符后分析数据
 * Calls:         SIM900A_parse_input()
 * Called By:     串口中断
 * Input:         byte  --字节数据
 * Return:        void
 * Others:        None
 ******************************************************************************/
void SIM900A_core_getch(uint8_t byte)
{
    if (l_serial_buffer.recv_en == 1) //接收使能
    {
        if (l_serial_buffer.index == 0)
        {
            memset (l_serial_buffer.buffer, 0,
             SERIAL_INPUT_BUFFER_MAX_LEN);//全内存区清空
            /*memset (l_serial_buffer.buffer, 0, strlen (l_serial_buffer.buffer));*/
        }
        *(l_serial_buffer.buffer + l_serial_buffer.index ++) = byte;

        if ((byte == '\n' && l_serial_buffer.last == '\r') || 
                byte == '>' || 
                byte == '\x1a' || 
                l_serial_buffer.index >= SERIAL_INPUT_BUFFER_MAX_LEN - 1) //判断一行命令结束
        {
            //分析字串
            *(l_serial_buffer.buffer + l_serial_buffer.index) = '\0'; //增加字符串结束标识
            l_sim_cmdline.buffer = l_serial_buffer.buffer;
            l_serial_buffer.index = 0;
            /*SIM900A_parse_input (&l_sim_cmdline);*/
            _SIM900A_parse_input (&l_sim_cmdline);
        }
        l_serial_buffer.last = byte;
    }
}

